package com.azzcs.spring.bean;

import com.alibaba.druid.util.StringUtils;
import com.azzcs.customer.service.TransferServiceImpl;
import com.azzcs.spring.anno.*;
import com.azzcs.spring.factory.config.BeanFactoryAware;
import com.azzcs.spring.factory.config.BeanFactoryPostProcessor;
import com.azzcs.spring.factory.config.BeanPostProcessor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;

/**
 * @Author: wzg
 * @Date: 2020/12/19 下午3:18
 */
public class AnnotatedBeanDefinition implements BeanDefinition{
    private String beanName;
    private Class clazz;
    private boolean isConfiguration = false;
    private Set<String> basePackages = new HashSet<>();
    private boolean isBean = false;
    private Set<PropertyValue> propertyValues = new HashSet<>();
    private Set<String> alias = new HashSet<>();

    private static Set<Class> ignoreAlias = new HashSet<>();
    static {
        ignoreAlias.add(BeanFactoryAware.class);
        ignoreAlias.add(BeanFactoryPostProcessor.class);
        ignoreAlias.add(BeanPostProcessor.class);
    }

    public AnnotatedBeanDefinition(Class<?> componentClass) {
        parseBeanName(componentClass);
        parseClass(componentClass);
        parseAnnotation(componentClass);
        parsePropertyValue(componentClass);
        parseAlias(componentClass);
    }

    private void parseAlias(Class<?> componentClass) {

        if(isBean){
            Class<?>[] interfaces = componentClass.getInterfaces();
            for (Class<?> anInterface : interfaces) {
                String name = anInterface.getName();
                if(ignoreAlias.contains(name)){
                    continue;
                }
                alias.add(anInterface.getName());
            }
        }
    }

    /**
     * 解析属性
     * @param componentClass
     */
    private void parsePropertyValue(Class<?> componentClass) {
        Field[] declaredFields = componentClass.getDeclaredFields();
        for (Field field : declaredFields) {
            Annotation[] annotations = field.getAnnotations();
            for (Annotation annotation : annotations) {
                if(annotation instanceof Autowired){
                    propertyValues.add(new PropertyValue(field.getName(),field.getType()));
                }
            }
        }
    }

    private void parseAnnotation(Class<?> componentClass) {
        Annotation[] annotations = componentClass.getAnnotations();
        for (Annotation annotation : annotations) {
            if(annotation instanceof ComponentScan){
                parseComponentScan((ComponentScan) annotation);
            }
            if(annotation instanceof Component){
                parseComponent((Component) annotation);
            }
            if(annotation instanceof Repository){
                parseRepository((Repository) annotation);
            }
            if(annotation instanceof Service){
                parseService((Service) annotation);
            }
        }
    }

    private void parseClass(Class<?> componentClass) {
        this.clazz = componentClass;
    }

    private void parseBeanName(Class<?> componentClass) {
        beanName = toLowerCaseFirstOne(componentClass.getSimpleName());
    }

    @Override
    public Set<PropertyValue> getPropertyValues() {
        return propertyValues;
    }

    public static void main(String[] args) {
        String simpleName = TransferServiceImpl.class.getSimpleName();
        System.out.println(toLowerCaseFirstOne(simpleName));
    }


    public static String toLowerCaseFirstOne(String s){
        if(Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }
    private void parseService(Service annotation) {
        String beanName = annotation.value();
        if(!StringUtils.isEmpty(beanName)){
            this.beanName = beanName;
        }
        this.isBean = true;
    }

    private void parseRepository(Repository annotation) {
        String beanName = annotation.value();
        if(!StringUtils.isEmpty(beanName)){
            this.beanName = beanName;
        }
        this.isBean = true;
    }

    private void parseComponent(Component annotation) {
        String beanName = annotation.value();
        if(!StringUtils.isEmpty(beanName)){
            this.beanName = beanName;
        }
        this.isBean = true;
    }

    private void parseComponentScan(ComponentScan annotation) {
        isConfiguration = true;
        String basePackage = annotation.value();
        basePackages.add(basePackage);
        this.isBean = true;
    }

    @Override
    public String getBeanName() {
        return beanName;
    }


    @Override
    public Class<?> getBeanClass() {
        return clazz;
    }

    @Override
    public boolean isConfiguration() {
        return isConfiguration;
    }

    @Override
    public Set<String> getBasePackages() {
        return basePackages;
    }

    @Override
    public boolean isBean() {
        return isBean;
    }

    @Override
    public Set<String> getAlias() {
        return alias;
    }
}
